{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Wilkinson Power Divider"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In this notebook we create a [Wilkinson power divider](https://www.microwaves101.com/encyclopedias/wilkinson-power-splitters), which splits an input signal into two equals phase output signals. Theoretical results about this circuit are exposed in reference [1]. Here we will reproduce the ideal circuit illustrated below and discussed in reference [2]. In this example, the circuit is designed to operate at 1 GHz.\n",
    "\n",
    "<img src=\"wilkinson_power_divider.png\">\n",
    "\n",
    " - [1] P. Hallbjörner, Microw. Opt. Technol. Lett. 38, 99 (2003).\n",
    " - [2] Microwaves 101: \"Wilkinson Power Splitters\" "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# standard imports\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "\n",
    "import skrf as rf\n",
    "\n",
    "rf.stylely()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# frequency band\n",
    "freq = rf.Frequency(start=0, stop=2, npoints=501, unit='GHz')\n",
    "\n",
    "# characteristic impedance of the ports\n",
    "z0_ports = 50\n",
    "\n",
    "# resistor\n",
    "R = 100\n",
    "line_resistor = rf.media.DefinedGammaZ0(frequency=freq, z0=R)\n",
    "resistor = line_resistor.resistor(R, name='resistor')\n",
    "\n",
    "# branches\n",
    "z0_branches = np.sqrt(2)*z0_ports\n",
    "beta = freq.w/rf.c\n",
    "line_branches = rf.media.DefinedGammaZ0(frequency=freq, z0=z0_branches, gamma=0+beta*1j)\n",
    "\n",
    "d = line_branches.theta_2_d(90, deg=True)  # @ 90°(lambda/4)@ 1 GHz is ~ 75 mm\n",
    "branch1 = line_branches.line(d, unit='m', name='branch1')\n",
    "branch2 = line_branches.line(d, unit='m', name='branch2')\n",
    "\n",
    "# ports\n",
    "port1 = rf.Circuit.Port(freq, name='port1', z0=50)\n",
    "port2 = rf.Circuit.Port(freq, name='port2', z0=50)\n",
    "port3 = rf.Circuit.Port(freq, name='port3', z0=50)\n",
    "\n",
    "# Connection setup\n",
    "#┬Note that the order of appearance of the port in the setup is important\n",
    "connections = [\n",
    "           [(port1, 0), (branch1, 0), (branch2, 0)],\n",
    "           [(port2, 0), (branch1, 1), (resistor, 0)],\n",
    "           [(port3, 0), (branch2, 1), (resistor, 1)]\n",
    "        ]\n",
    "\n",
    "# Building the circuit\n",
    "C = rf.Circuit(connections)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The circuit setup can be checked by visualising the circuit graph (this requires the python package `networkx` to be available). "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "C.plot_graph(network_labels=True, edge_labels=True, port_labels=True, port_fontize=2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's look to the scattering parameters of the circuit:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fig, (ax1,ax2) = plt.subplots(2, 1, sharex=True)\n",
    "C.network.plot_s_db(ax=ax1, m=0, n=0,  lw=2)  # S11\n",
    "C.network.plot_s_db(ax=ax1, m=1, n=1,  lw=2)  # S22\n",
    "ax1.set_ylim(-90, 0)\n",
    "C.network.plot_s_db(ax=ax2, m=1, n=0,  lw=2)  # S21\n",
    "C.network.plot_s_db(ax=ax2, m=2, n=0,  ls='--', lw=2)  # S31\n",
    "ax2.set_ylim(-4, 0)\n",
    "fig.suptitle('Ideal Wilkinson Divider @ 1 GHz')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Currents and Voltages\n",
    "In the previous examples, we didn't have many internal ports because we connected the N ports directly to the external ports. However, in more complex scenarios, circuits can have many internal ports.\n",
    "\n",
    "Additionally, the earlier examples featured circuits with components connected in series. As circuit complexity increases, it becomes inevitable that some components will be connected in parallel, which introduces new challenges for calculating current and voltage.\n",
    "\n",
    "Fortunately, scikit-rf is well-equipped to handle these complex circuit scenarios. It is possible to calculate the currents and voltages at the circuit's internal ports."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "raises-exception"
    ]
   },
   "outputs": [],
   "source": [
    "power = [1,0,0]\n",
    "phase = [0,0,0]\n",
    "C.voltages(power, phase)  # or C2.currents(power, phase)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Alternatively, you can use splitting Networks, such as \"T\" Networks in our case, to create circuits with only pairs of connections and perform current and voltage calculations. While using splitting Networks aligns more closely with 'classic' way for building a circuit, it has disadvantages in terms of code readability, complexity, and computational performance."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tee1 = line_branches.tee(name='tee1')\n",
    "tee2 = line_branches.tee(name='tee2')\n",
    "tee3 = line_branches.tee(name='tee3')\n",
    "\n",
    "cnx = [\n",
    "    [(port1, 0), (tee1, 0)],\n",
    "    [(tee1, 1), (branch1, 0)],\n",
    "    [(tee1, 2), (branch2, 0)],\n",
    "    [(branch1, 1), (tee2, 0)],\n",
    "    [(branch2, 1), (tee3, 0)],\n",
    "    [(tee2, 2), (resistor, 0)],\n",
    "    [(tee3, 2), (resistor, 1)],\n",
    "    [(tee3, 1), (port3, 0)],\n",
    "    [(tee2, 1), (port2, 0)],\n",
    "]\n",
    "C2 = rf.Circuit(cnx)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The resulting graph is a bit more stuffed:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "C2.plot_graph(network_labels=True, edge_labels=True, port_labels=True, port_fontize=2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "But the results are the same:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "C.network == C2.network"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fig, (ax1,ax2) = plt.subplots(2, 1, sharex=True)\n",
    "C2.network.plot_s_db(ax=ax1, m=0, n=0,  lw=2)  # S11\n",
    "C2.network.plot_s_db(ax=ax1, m=1, n=1,  lw=2)  # S22\n",
    "ax1.set_ylim(-90, 0)\n",
    "C2.network.plot_s_db(ax=ax2, m=1, n=0,  lw=2)  # S21\n",
    "C2.network.plot_s_db(ax=ax2, m=2, n=0,  ls='--', lw=2)  # S31\n",
    "ax2.set_ylim(-4, 0)\n",
    "fig.suptitle('Ideal Wilkinson Divider (2nd way) @ 1 GHz')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And the internal voltages and currents are also consistent."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "C2.voltages(power, phase)  # or C2.currents(power, phase)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You will find more details on voltages and currents calculation on the dedicated example."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "celltoolbar": "Tags",
  "kernelspec": {
   "display_name": "Python 3.10.6 ('.venv': venv)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.6"
  },
  "vscode": {
   "interpreter": {
    "hash": "637c323cf467337602e9974a89cb4d3fc95fac3ef875a73e62754f8e768d8de7"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
